package com.koro.service.impl;

import com.koro.cache.RedisService;
import com.koro.dto.FindGoodsDTO;
import com.koro.dto.FindUsersDTO;
import com.koro.dto.SaveOrdersDTO;
import com.koro.feign.GoodsFeignClient;
import com.koro.feign.OrderFeignClient;
import com.koro.feign.UsersFeigunClient;
import com.koro.lock.Lock;
import com.koro.lock.RedisDistributedLockHandler;
import com.koro.message.MessageQueueHelper;
import com.koro.service.FlashSaleService;
import com.koro.vo.BaseException;
import com.koro.vo.FindGoodsVO;
import com.koro.vo.FindUsersVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@Service
@Slf4j
public class FlashSaleServiceImpl implements FlashSaleService {

    @Autowired
    private UsersFeigunClient usersFeigunClient;
    @Autowired
    private RedisService redisService;
    @Autowired
    private RedisDistributedLockHandler redisDistributedLockHandler;
    @Autowired
    private GoodsFeignClient goodsFeignClient;
    @Autowired
    private OrderFeignClient orderFeignClient;
    @Autowired
    private MessageQueueHelper messageQueueHelper;
    @Autowired
    private RedisTemplate redisTemplate;

    private static final String LUA_SCRIPT =
            "if tonumber(redis.call('get',KEY[1])) > 0 " +
            "and tonumber(redis.call('SISMEMBER',KEY[2],ARGV[1])) == 0 then " +
            "redis.call('incrby',KEYS[1],'-1') return 1 else return 0 end" ;


    private static final String LUA_SET = "return redis.call('SISMEMBER',KEY[1],ARGV[1])";

    private static final String LUA_STRING = "return redis.call('SET', KEYS[1], ARGV[1])";

    @Override
    public void prebook(Integer id) {

        List<FindUsersVO> vos = usersFeigunClient.findAll(1).getData();

        vos.forEach(s -> {
            Lock lock = new Lock("prebookLock", "prebook");
            if(redisDistributedLockHandler.tryLock(lock)) {
                // prebooknum
                Integer prebooknum = (Integer) redisService.get("prebooknum");
                if(prebooknum <= 0) {
                    redisDistributedLockHandler.releaseLock(lock);
                    throw new BaseException("预约已满,用户id:" + s.getId());
                }

                Long prebook_user = redisService.sadd("prebook_user", s.getId());
                if(prebook_user == 0) {
                    redisDistributedLockHandler.releaseLock(lock);
                    throw new BaseException("你已有预约,用户id:" + s.getId());
                }
                redisService.decr("prebooknum");
                redisDistributedLockHandler.releaseLock(lock);
            }
        });
    }

    @Override
    public void cacheGoods(Integer id) {
        FindGoodsDTO findGoodsDTO = new FindGoodsDTO();
        findGoodsDTO.setId(id);
        FindGoodsVO findGoodsVO = goodsFeignClient.findById(findGoodsDTO).getData();
        if(ObjectUtils.isEmpty(findGoodsVO)) {
            throw new BaseException("商品不存在.");
        }
    //    redisService.set("goods",findGoodsVO.getStock());
        for (int i = 0 ; i < findGoodsVO.getStock() ; i++) {
            redisService.rightPush("goods",id);
        }
    }

    @Override
    public void panicBuying(Integer id) {
       /* DefaultRedisScript<Boolean> script = new DefaultRedisScript<>();
        script.setScriptText(LUA_SET);
        script.setResultType(Boolean.class);

        ArrayList<String> list = new ArrayList<>();
     //   list.add("goods");
        list.add("prebook_user");
        Boolean myValue = (Boolean) redisTemplate.execute(script, list, id);
        System.out.println(myValue);*/
        // 判断用户是否是在预约列表
        if(!redisService.isMember("prebook_user",id)) {
            throw new BaseException("您未预约,用户id:" + id);
        }
        Integer goodsId = (Integer) redisService.leftPop("goods");
        if(ObjectUtils.isEmpty(goodsId)) {
            throw new BaseException("商品已被抢购完毕.");
        }


        SaveOrdersDTO dto = new SaveOrdersDTO();
        dto.setUserId(id);
        dto.setGoodsId(goodsId);
        // 发送消息到RabbitMQ 异步下单
        messageQueueHelper.sendMessage("seckill-order-ex","seckill.qu","saveordersdto",dto);

    }

    @Override
    public Integer sub(SaveOrdersDTO dto) {
        //用户信息
        FindUsersDTO findUsersDTO = new FindUsersDTO();
        findUsersDTO.setId(dto.getUserId());
        FindUsersVO findUsersVO = usersFeigunClient.findById(findUsersDTO).getData();

        dto.setUserId(findUsersVO.getId());
        dto.setUsername(findUsersVO.getUsername());
        //商品信息
        FindGoodsDTO findGoodsDTO = new FindGoodsDTO();
        findGoodsDTO.setId(dto.getGoodsId());
        FindGoodsVO findGoodsVO = goodsFeignClient.findById(findGoodsDTO).getData();

        dto.setGoodsId(findGoodsVO.getId());
        dto.setGoodsName(findGoodsVO.getGoodsName());
        dto.setOrderNo(String.valueOf(new Random(1000).nextInt()));
        dto.setNum(1);
        dto.setTotalPrice(findGoodsVO.getPrice());

        Integer orderId = orderFeignClient.save(dto).getData();

        redisService.remove("prebook_user",dto.getUserId());

        // 更新秒杀商品库存
        goodsFeignClient.updataseckill(dto.getGoodsId());

        return orderId;
    }


}
